package com.mars.base.service;

import java.util.List;

import com.github.pagehelper.PageInfo;
import com.mars.base.common.exception.AppException;
import com.mars.base.common.utils.page.PageParam;

/**
 * 基础 Service 接口<br>
 * Service接口可以继承该基础接口，该接口定义了基础的CRUD<br>
 * 该Service基础接口不是必须的
 * 
 * <p>标题: IService</p>
 * <p>描述: </p>
 * <p>公司: www.yhaoquan.com</p> 
 * @作者： 杨浩泉
 * @日期：2016年11月25日
 * @版本：1.0
 */
public interface IService<T, PK> {

	/**
	 * 插入一条记录
	 * @param entity 实体对象
	 * @return
	 * @throws AppException
	 */
	int insert(T entity) throws AppException;

	/**
	 * 插入一条记录（选择字段， null 字段不插入）
	 * @param entity 实体对象
	 * @return
	 * @throws AppException
	 */
	int insertSelective(T entity) throws AppException;

	/**
	 * 批量插入，支持批量插入的数据库可以使用，例如MySQL,H2等，另外该接口限制实体包含`id`属性并且必须为自增列，该方法不适合 Oracle
	 * @param entityList 实体对象列表
	 * @return
	 * @throws AppException
	 */
	int insertBatch(List<T> entityList) throws AppException;

	/**
	 * <p>
	 * 保存或修改记录，<b style="color:red">需要自己定义相应的Mapper标签</b>
	 * </p>
	 * 如下例子：
	 * 
	 * <pre>
	 * &lt;insert id="inserOrUpdate"&gt;
	 * 	&lt;selectKey keyProperty="count" resultType="int" order="BEFORE"&gt;
	 * 	select count(id) from tb_user where id = #{id}
	 * &lt;/selectKey&gt;
	 * &lt;if test="count &gt; 0"&gt;
	 * 	update tb_user
	 * 	set account = #{account}
	 * 	where id = #{id}
	 * &lt;/if&gt;
	 * &lt;if test="count==0"&gt;
	 * 	insert into tb_user(id, account) values(#{id},#{account})
	 * &lt;/if&gt;
	 * &lt;/insert&gt;
	 * </pre>
	 * 
	 * <p>
	 * 其中keyProperty是Java对象的属性名
	 * </p>
	 * 
	 * @param entity
	 *            实体对象
	 * @return
	 */
	int inserOrUpdate(T entity) throws AppException;

	/**
	 * 根据 ID 删除
	 * @param id 主键ID
	 * @return
	 * @throws AppException
	 */
	int delete(PK id) throws AppException;
	
	/**
	 * 根据 entity 条件，删除记录
	 * @param entity 实体对象
	 * @return
	 * @throws AppException
	 */
	int deleteSelective(T entity) throws AppException;

	/**
	 * 删除（根据ID 批量删除），<b style="color:red">需要自己定义相应的Mapper标签</b>
	 * @param idList 主键ID集合
	 * @return
	 * @throws AppException
	 */
	int deleteByIds(List<PK> idList) throws AppException;
	
	/**
	 * 删除（根据ID 批量删除）
	 * @param ids 字符串(1,2,3,4)
	 * @return
	 * @throws AppException
	 */
	int deleteByIds(String ids) throws AppException;

	/**
	 * 根据 ID 修改
	 * @param entity 实体对象
	 * @return
	 * @throws AppException
	 */
	int update(T entity) throws AppException;

	/**
	 * 根据 ID 选择修改
	 * @param entity 实体对象
	 * @return
	 * @throws AppException
	 */
	int updateSelective(T entity) throws AppException;

	/**
	 * 根据 whereEntity 条件更新记录，<b style="color:red">需要自己定义相应的Mapper标签</b>
	 * @param entity 实体对象
	 * @param whereEntity 实体查询条件
	 * @return
	 * @throws AppException
	 */
	int update(T entity, T whereEntity) throws AppException;

	/**
	 * 根据 whereEntity 条件选择更新记录，<b style="color:red">需要自己定义相应的Mapper标签</b>
	 * @param entity 实体对象
	 * @param whereEntity 实体查询条件（可以为 null）
	 * @return
	 * @throws AppException
	 */
	int updateSelective(T entity, T whereEntity) throws AppException;

	/**
	 * 根据ID 批量更新，<b style="color:red">需要自己定义相应的Mapper标签</b>
	 * @param entityList 实体对象列表
	 * @return
	 * @throws AppException
	 */
	int updateBatchById(List<T> entityList) throws AppException;

	/**
	 * 根据 ID 查询
	 * @param id 主键ID
	 * @return
	 * @throws AppException
	 */
	T selectById(PK id) throws AppException;

	/**
	 * 查询（根据ID 批量查询），<b style="color:red">需要自己定义相应的Mapper标签</b>
	 * @param idList 主键ID集合
	 * @return
	 * @throws AppException
	 */
	List<T> selectByIds(List<PK> idList) throws AppException;
	
	/**
	 * 查询（根据ID 批量查询）
	 * @param ids 字符串(1,2,3)
	 * @return
	 * @throws AppException
	 */
	List<T> selectByIds(String ids) throws AppException;

	/**
	 * 根据 entity 条件，查询一条记录
	 * @param entity 实体对象
	 * @return
	 * @throws AppException
	 */
	T selectOne(T entity) throws AppException;
	
	/**
	 * 根据 entity 条件，查询总记录数
	 * @param entity 实体对象
	 * @return
	 * @throws AppException
	 */
	int selectCount(T entity) throws AppException;
	
	/**
	 * 查询列表
	 * @return T
	 * @throws AppException
	 */
	List<T> selectAll() throws AppException;
	
	/**
	 * 查询列表
	 * @param entity 条件（实体对象），select(null)方法能达到同样的效果
	 * @return T
	 * @throws AppException
	 */
	List<T> selectList(T entity) throws AppException;
	
	/**
	 * 查询列表，排序  <b style="color:red">需要自己定义相应的Mapper标签</b>
	 * @param entity entity 条件（实体对象），select(null)方法能达到同样的效果
	 * @param orderby 排序条件
	 * @return T
	 * @throws AppException
	 */
	List<T> selectList(T entity, String orderBy) throws AppException;

	/**
	 * 翻页查询
	 * @param pagepram 分页对象
	 * @return Page 分页对象
	 * @throws AppException
	 */
	PageInfo<T> selectPage(PageParam pageParam) throws AppException;
	
	/**
	 * 翻页查询
	 * @param pagepram 分页对象
	 * @param entity 筛选条件
	 * @return Page 分页对象
	 * @throws AppException
	 */
	PageInfo<T> selectPage(PageParam pageParam, T entity) throws AppException;
	
	/**
	 * 检查字段的值是否存在 <b style="color:red">需要自己定义相应的Mapper标签</b>
	 * @param field 数据库字段
	 * @param value 值
	 * @return
	 * @throws AppException
	 */
	T checkValue(String field, Object value) throws AppException;
	
}
